package com.ruoyi.web.controller.common;

import cn.hutool.captcha.AbstractCaptcha;
import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.CaptchaType;
import com.ruoyi.common.enums.EmailEnums;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.annotation.AllowAccess;
import com.ruoyi.framework.config.properties.CaptchaProperties;
import com.ruoyi.system.domain.SysOss;
import com.ruoyi.system.domain.vo.SysDictDataVo;
import com.ruoyi.system.service.EmailUtilsServer;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDictTypeService;
import com.ruoyi.system.service.ISysOssService;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * 通用工具
 *
 * @author Lion Li
 */
@Api(value = "通用工具", tags = {"通用工具"})
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/common")
public class CommonController {

    private final CaptchaProperties captchaProperties;
    private final ISysConfigService configService;
    private final ISysDictTypeService dictTypeService;
    private final ISysOssService iSysOssService;
    private final EmailUtilsServer emailUtilsServer;

    /**
     * 生成验证码
     */
    @AllowAccess
    @ApiOperation("生成图形验证码")
    @GetMapping("/captchaImage")
    public R<Map<String, Object>> getCode() {
        Map<String, Object> ajax = new HashMap<>();
        boolean captchaOnOff = configService.selectCaptchaOnOff();
        ajax.put("captchaOnOff", captchaOnOff);
        if (!captchaOnOff) {
            return R.ok(ajax);
        }
        // 保存验证码信息
        String uuid = IdUtil.simpleUUID();
        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
        // 生成验证码
        CaptchaType captchaType = captchaProperties.getType();
        boolean isMath = CaptchaType.MATH == captchaType;
        Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength();
        CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length);
        AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
        captcha.setGenerator(codeGenerator);
        captcha.createCode();
        String code = isMath ? getCodeResult(captcha.getCode()) : captcha.getCode();
        RedisUtils.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        ajax.put("uuid", uuid);
        ajax.put("img", captcha.getImageBase64());
        ajax.put("code", code);
        return R.ok(ajax);
    }

    /**
     * 发送邮箱验证
     */
    @AllowAccess
    @ApiOperation("发送邮箱验证码")
    @GetMapping("/toEmail")
    public R toEmail(@ApiParam("邮箱") @NotNull(message = "邮箱不能为空") String email,
                     @ApiParam("邮件类型 1:注册邮件 2:登陆邮件 3:修改密码") @NotBlank(message = "邮件类型不能为空") Integer type) {
        // 校验邮箱格式
        Pattern regex = Pattern.compile(Constants.EMAIL_REGEX);
        if (!regex.matcher(email).matches()) {
            R.fail("邮箱格式错误");
        }
        EmailEnums enums = null;
        switch (type) {
            case 1:
                enums = EmailEnums.REGISTER_EMAIL;
                break;
            case 2:
                enums = EmailEnums.LOGIN_EMAIL;
                break;
            case 3:
                enums = EmailEnums.EDIT_PASSWORD;
                break;
            default:
                return R.fail("邮件类型错误");
        }

//        // 获取用户信息
//        MedicineUserInfo userInfo = userInfoService.getByEmail(email);
//        if (type != 1 && userInfo == null) {
//            return R.fail("用户不存在");
//        }

        Map<String, Object> data = emailUtilsServer.CheckToEmail(email, enums);
        if (data != null) {
            return R.ok(data);
        }
        return R.fail("发送失败！");
    }

    private String getCodeResult(String capStr) {
        int numberLength = captchaProperties.getNumberLength();
        int a = Convert.toInt(StringUtils.substring(capStr, 0, numberLength).trim());
        char operator = capStr.charAt(numberLength);
        int b = Convert.toInt(StringUtils.substring(capStr, numberLength + 1, numberLength + 1 + numberLength).trim());
        switch (operator) {
            case '*':
                return Convert.toStr(a * b);
            case '+':
                return Convert.toStr(a + b);
            case '-':
                return Convert.toStr(a - b);
            default:
                return StringUtils.EMPTY;
        }
    }

    /**
     * 根据字典类型查询字典数据信息
     */
    @AllowAccess
    @ApiOperation("根据字典类型查询字典数据信息,商品类型：goods_type，产地：place_of_origin")
    @GetMapping(value = "/dict/{dictType}")
    public R<List<SysDictDataVo>> dictType(@ApiParam("字典类型") @PathVariable String dictType) {
        List<SysDictDataVo> data = dictTypeService.selectDictDataVoByType(dictType);
        if (ObjectUtil.isNull(data)) {
            data = new ArrayList<>();
        }
        return R.ok(data);
    }

    /**
     * 上传图片
     */
    @ApiOperation("上传图片")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "image", value = "上传图片", paramType = "query", dataTypeClass = File.class, required = true)
    })
    @Log(title = "上传图片", businessType = BusinessType.UPDATE)
    @PostMapping("/upload/image")
    public R<Map<String, Object>> avatar(@RequestPart("image") MultipartFile file) {
        Map<String, Object> ajax = new HashMap<>();
        if (!file.isEmpty()) {
            SysOss oss = iSysOssService.upload(file);
            ajax.put("imgUrl", oss.getUrl());
            return R.ok(ajax);
        }
        return R.fail("上传图片异常，请联系管理员");
    }

}
